#ifndef __DLL_INJECT__
#define __DLL_INJECT__

namespace mm
{
	static long inject_dll( HANDLE hProcess, LPCSTR aFileName )
	{
		PVOID lpAddr = 0;
		SIZE_T sWant = 0x1000;
		NTSTATUS nts = NtAllocateVirtualMemory( hProcess, &lpAddr, 0, &sWant, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
		if( nts < 0 ) return E_FAIL;
		SIZE_T cbEff = 0;
		nts = NtWriteVirtualMemory( hProcess, lpAddr, aFileName, strlen(aFileName) + 1, &cbEff );
		if( nts < 0 ) 
		{
			NtFreeVirtualMemory( hProcess, &lpAddr, &sWant, MEM_RELEASE );
			return E_FAIL;
		}
		HANDLE hThread = CreateRemoteThread( hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibraryA, NULL, 0, NULL );
		if( !hThread ) 
		{
			NtFreeVirtualMemory( hProcess, &lpAddr, &sWant, MEM_RELEASE );
			return E_FAIL;
		}

		DWORD wr = WaitForSingleObject( hThread, 5000 );
		if( wr != WAIT_OBJECT_0 )
		{
			NtTerminateThread(hThread,0);
			NtFreeVirtualMemory( hProcess, &lpAddr, &sWant, MEM_RELEASE );
			NtClose(hThread);
			return E_FAIL;
		}

		DWORD dwMod = 0;
		BOOL fok = GetExitCodeThread( hThread, &dwMod );
		NtFreeVirtualMemory( hProcess, &lpAddr, &sWant, MEM_RELEASE );
		CloseHandle( hThread );
		return (dwMod != 0) ? S_OK : E_FAIL;
	}

	//size_t _on_nt_resume_thread( hk::exec_context * pctx )
	//{
	//	HANDLE ThreadHandle = (HANDLE)pctx->args[0];
	//	PULONG SuspendCount = (PULONG)pctx->args[1];

	//	THREAD_BASIC_INFORMATION tbi = {};
	//	ULONG ulOutSize = 0;
	//	NTSTATUS nts = NtQueryInformationThread(ThreadHandle, ThreadBasicInformation, &tbi, sizeof(tbi), &ulOutSize );
	//	if( nts < 0 ) return true;

	//	CONTEXT ctx = {};
	//	NtGetContextThread( ctx );
	//}


};

#endif